package com.service.impl;

import com.alibaba.fastjson.JSON;
import com.bean.JwtOperation;
import com.dto.RoleSmallDto;
import com.dto.User;
import com.entity.Role;
import com.entity.RoleAndMenu;
import com.exception.DisabledLoginException;
import com.repository.MenuAndRoleRepository;
import com.repository.RoleRepository;
import com.service.RoleService;
import com.service.mapstruct.RoleSmallMapper;
import com.vo.ConstantVo;
import com.vo.RoleVo;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author Yadasu
 * @date 2020/12/21 16:59
 */
@Service
@RequiredArgsConstructor
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleRepository repository;
    @Autowired
    private JwtOperation jwtOperation;
    @Autowired
    private MenuAndRoleRepository menuAndRoleRepository;

    private final RoleSmallMapper roleSmallMapper;



    @Override
    public List<Role> findAllRoles() {
        return repository.findAll();
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Role updateRoleStatus(Role role) {
        return repository.save(role);
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void editRole(Role role, String token) {
        try {
            Claims claims = jwtOperation.parseJwt(token);
            User user = JSON.parseObject(String.valueOf(claims.get("user")), User.class);
            role.setUpdatedBy(user.getName());
            role.setUpdatedTime(new Date());
            repository.save(role);
        } catch (Exception e) {
            throw new DisabledLoginException("token不存在或过期");
        }


    }

    @Override
    public Role findRoleByRid(Integer rid) {
        if (repository.findById(rid).isPresent()) {
            return repository.findById(rid).get();
        }
        return null;
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addRole(RoleVo roleVo, String token) {
        try {
            Claims claims = jwtOperation.parseJwt(token);
            User user = JSON.parseObject(String.valueOf(claims.get("user")), User.class);
            roleVo.getRole().setCreatedBy(user.getName());
            roleVo.getRole().setCreatedTime(new Date());
            repository.save(roleVo.getRole());
            Role byName = repository.findByName(roleVo.getRole().getName());
            for (int i = 0; i < roleVo.getId().size(); i++) {
                menuAndRoleRepository.add(roleVo.getId().get(i), byName.getId());
            }
        } catch (Exception e) {
            throw new DisabledLoginException("token不存在或过期");
        }

    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void changeRole(ConstantVo constantVo, String token) {
        try {
            if (repository.findById(constantVo.getRid()).isPresent()) {
                Role role = repository.findById(constantVo.getRid()).get();
                Claims claims = jwtOperation.parseJwt(token);
                User user = JSON.parseObject(String.valueOf(claims.get("user")), User.class);
                role.setCreatedBy(user.getName());
                role.setCreatedTime(new Date());
                repository.save(role);
                if (constantVo.getId().size() > 0)
                    for (int i = 0; i < constantVo.getId().size(); i++) {
                        menuAndRoleRepository.add(constantVo.getId().get(i), constantVo.getRid());
                    }
                else {
                    menuAndRoleRepository.delMenuInRole(constantVo.getRid());
                }
            }
        } catch (Exception e) {
            throw new DisabledLoginException("token不存在或过期");
        }

    }

    @Override
    public boolean findById(Integer id) {
        Optional<Role> optional = repository.findById(id);
        return optional.isPresent();
    }

    @Override
    public boolean findByIds(List<Integer> ids) {
        List<Role> all = repository.findAllById(ids);
        return all.size() == ids.size();
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteRoleByIds(List<Integer> ids) {
        List<Integer> list = ids;
        for (Integer id : list) {
            Optional<Role> optional = repository.findById(id);
            if (optional.isPresent()) {
                repository.deleteById(id);
                menuAndRoleRepository.delMenuInRole(id);
            }
        }
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteRoleById(Integer id) {
        Optional<Role> optional = repository.findById(id);
        if (optional.isPresent()) {
            repository.deleteById(id);
            menuAndRoleRepository.delMenuInRole(id);
        }
    }

    @Override
    public List<RoleSmallDto> findByUsersId(Long id) {
        return roleSmallMapper.toDto(new ArrayList<>(repository.findByUserId(id)));
    }
}
